#include "Controller.h"
#include "Network.h"

Network * network_new(Controller *controller) {
	Network *nt = (Network *) malloc(sizeof(Network));
	nt->controller = controller;
	return nt;
}

void network_start(Network *network) {
	network->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	network->size = sizeof(network->address);
	bzero(&network->address, network->size);
	network->address.sin_family = PF_INET;
	network->address.sin_port = htons(network->port);
	network->address.sin_addr.s_addr = htonl(INADDR_ANY);
	if(bind(network->socket, (struct sockaddr*) &network->address, network->size) != ERROR) {
		if(listen(network->socket, network->connections) == ERROR)
			Throw 0;
		else printf("Listening port %d...\n", network->port);
	}
	else Throw 0;
}

void network_stop(Network *network) {
	close(network->socket);
	g_list_free_full(network->clients, network_free_client);
}

/*
void network_accept(Network *network) {
	while(true) {
		if(g_list_length(network->clients) < network->connections) {
			Client *cl = (Client *) malloc(sizeof(Client));
			cl->socket = accept(network->socket, (struct sockaddr *) &cl->address, &cl->size);
			if(cl->socket != ERROR) {
				network->clients = g_list_prepend(network->clients, cl);
				NetworkReceiveArg arg;
				arg.controller = network->controller;
				arg.client = g_list_first(network->clients)->data;
				if(pthread_create(&cl->thread, NULL, network_receive, (void *) &arg) == ERROR)
					Throw 0;
				else printf("Connection accepted!\n");
			}
			else {
				free(cl);
				Throw 0;
			}
		}
	}
}

void * network_receive(void *params) {
	Controller *ct = ((NetworkReceiveArg *) params)->controller;
	Client *cl = ((NetworkReceiveArg *) params)->client;
	char message[MAX_REQUEST_SIZE];
	while(true) {
		bzero(message, sizeof(message));
		switch(recv(cl->socket, message, sizeof(message), 0)) {
			case 0:
			case ERROR:
				controller_handle_error(ct, cl, 500);
				return NULL;
				break;
			default:
				printf("Receiving message...\n\n%s", message);
				controller_execute_request(ct, cl, message);
				break;
		}
	}
	return NULL;
}
*/

void network_accept(Network *network) {
	while(true) {
		Client *cl = (Client *) malloc(sizeof(Client));
		cl->socket = accept(network->socket, (struct sockaddr *) &cl->address, &cl->size);
		if(cl->socket != ERROR) {
			printf("Connection accepted!\n");
			network_receive(network->controller, cl);
			close(cl->socket);
			free(cl);
		}
		else Throw 0;
	}
}

void network_receive(Controller *controller, Client *client) {
	Controller *ct = controller;
	Client *cl = client;
	char message[MAX_REQUEST_SIZE];
	bzero(message, sizeof(message));
	switch(recv(cl->socket, message, sizeof(message), 0)) {
		case 0:
		case ERROR:
			controller_handle_error(ct, cl, 500);
			break;
		default:
			printf("Receiving message...\n\n%s", message);
			controller_execute_request(ct, cl, message);
			break;
	}
}

void network_send_response(Client *client, char *data) {
	char message[MAX_RESPONSE_SIZE] = "";
	sprintf(message, "HTTP/1.1 200 OK\naccess-control-allow-origin:*\nServer: Galactus\nContent-Length: %d\nContent-Type: application/json\nKeep-Alive:timeout=5, max=100\n\n%s", strlen(data), data);
	send(client->socket, message, sizeof(message), 0);
}

void network_send_error_500(Client *client) {
	char message[390] = "HTTP/1.1 500 Internal Server Error\nServer: Galactus\nAllow: GET\nContent-Length: 236\nConnection: close\nContent-Type: text/html; charset=utf-8\n\n<!DOCTYPE HTML><html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error</h1><p>The server encountered an unexpected condition which prevented it from fulfilling the request.<br /></p></body></html>";
	send(client->socket, message, sizeof(message), 0);
}

void network_free_client(gpointer item) {
	Client *client = (Client *) item;
	pthread_cancel(client->thread);
	free(client);
}

















